package com.muyun.intellij.plugin.background.image.rotation;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author He Lili
 * @date 2018/10/22
 */
public enum ImagesHandlerSingleton {

    /**
     * 实例
     */
    INSTANCE;
    private static final String BING_IMAGE_API = "https://cn.bing.com/HPImageArchive.aspx?format=js&n=1&pid=hp&idx=";

    private List<String> randomImageList = new ArrayList<String>();

    private String lastFolder = null;
    private int idx = 1;

    public String getRandomImage(String folder) {
        // 文件夹改动或者完成了一次循环
        if (!folder.equals(lastFolder) || collectionIsEmpty(randomImageList)) {
            // 如果配置了Bing的图片，先下载一张图片
            this.bingImage(folder);
            randomImageList.addAll(this.getRandomImageList(folder));
        }
        lastFolder = folder;
        while (!collectionIsEmpty(randomImageList) && !isImage(new File(randomImageList.get(0)))) {
            randomImageList.remove(0);
        }
        return collectionIsEmpty(randomImageList) ? null : randomImageList.remove(0);
    }

    private boolean isNotBlank(CharSequence cs) {
        int strLen = length(cs);
        if (strLen != 0) {
            for (int i = 0; i < strLen; ++i) {
                if (!Character.isWhitespace(cs.charAt(i))) {
                    return true;
                }
            }
        }
        return false;
    }

    private int length(CharSequence cs) {
        return cs == null ? 0 : cs.length();
    }

    private boolean collectionIsEmpty(List<String> list) {
        return null == list || list.isEmpty();
    }

    public void resetRandomImageList() {
        randomImageList = lastFolder == null ? null : this.getRandomImageList(lastFolder);
    }

    /**
     * 从必应下载图片
     *
     * @param folder 图片的保存路径
     * @return 返回下载后的图片的本地绝对路径
     */
    private String bingImage(String folder) {
        try {
            String imagePath = this.bingImageUrl();
            if (!this.isNotBlank(imagePath)) {
                return null;
            }
            String filePath = folder + File.separator + this.getImageName(imagePath);
            if (new File(filePath).exists()) {
                return null;
            }
            URL url = new URL("https://cn.bing.com" + imagePath);
            URLConnection urlConnection = url.openConnection();
            byte[] tmp = new byte[2048];
            int len;
            InputStream inputStream = null;
            FileOutputStream outputStream = null;
            try {
                inputStream = urlConnection.getInputStream();
                outputStream = new FileOutputStream(filePath);
                while ((len = inputStream.read(tmp)) > 0) {
                    outputStream.write(tmp, 0, len);
                }
                outputStream.flush();
                return filePath;
            } finally {
                if (null != outputStream) {
                    outputStream.close();
                }
                if (null != inputStream) {
                    inputStream.close();
                }
            }
        } catch (Throwable t) {
            NotificationCenter.notice(t.getMessage());
            return null;
        }
    }

    private String getImageName(String path) {
        return path.substring(path.indexOf("id=") + 3, path.indexOf("&"));
    }

    private String bingImageUrl() throws IOException {
        URL url = new URL(BING_IMAGE_API + (idx++));
        URLConnection urlConnection = url.openConnection();
        byte[] tmp = new byte[2048];
        int len;
        InputStream inputStream = null;
        ByteArrayOutputStream outputStream = null;
        try {
            inputStream = urlConnection.getInputStream();
            outputStream = new ByteArrayOutputStream();
            while ((len = inputStream.read(tmp)) > 0) {
                outputStream.write(tmp, 0, len);
            }
            String result = outputStream.toString("utf-8");
            // try {
            //     com.fasterxml.jackson.databind.ObjectMapper objectMapper = new com.fasterxml.jackson.databind.ObjectMapper();
            //     com.fasterxml.jackson.databind.JsonNode jsonNode = objectMapper.readTree(result);
            //     return jsonNode.get("images").get(0).get("url").asText();
            // } catch (Throwable t) {
                int urlIdx = result.indexOf("\"url\":\"");
                String imageUrlPart = result.substring(urlIdx + 7);
                return imageUrlPart.substring(0, imageUrlPart.indexOf("\",\"urlbase\":\""));
            // }
        } finally {
            if (null != outputStream) {
                outputStream.close();
            }
            if (null != inputStream) {
                inputStream.close();
            }
        }
    }

    private List<String> getRandomImageList(String folder) {
        if (folder.isEmpty()) {
            return new ArrayList<String>();
        }
        List<String> images = new ArrayList<String>();
        collectImages(images, folder);
        Collections.shuffle(images);
        return images;
    }

    private void collectImages(List<String> images, String folder) {
        File root = new File(folder);
        if (root.exists()) {
            File[] list = root.listFiles();
            if (list != null) {
                for (File f : list) {
                    if (f.isDirectory()) {
                        collectImages(images, f.getAbsolutePath());
                    } else {
                        if (isImage(f)) {
                            images.add(f.getAbsolutePath());
                        }
                    }
                }
            }
        }
    }

    private boolean isImage(File file) {
        String filename = file.getName();
        int dotPos = filename.lastIndexOf(".");
        if (dotPos < 0) {
            return false;
        } else {
            String fileExt = filename.substring(dotPos);
            if (fileExt.length() == 0) {
                return false;
            } else {
                return ".gif,.ief,.jpg,.jpeg,.jpe,.tiff,.tif,.png".contains(fileExt.toLowerCase());
            }
        }
    }

}
